﻿/*
 * Определяется местоположение образа на изображении в различных цветовых пространствах, масштабирование изображения
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace DiplomNN
{
    class BodyRecogn
    {
        public static void Allocation()
        {
            byte[, ,] ColorImage = Colors.BitmapToByteRgb(new Bitmap(Helper.ImageFromStartFormVideoPB));
            byte[, ,] BlakWhiteImage = Colors.BitmapToByteRgb(new Bitmap(Helper.ImageFromStartFormFilteredBinary));
            int[] ArrLine = new int[BlakWhiteImage.GetLength(1)];
            int[] ArrColumn = new int[BlakWhiteImage.GetLength(2)];

            for (int i = 0; i < BlakWhiteImage.GetLength(1); i++)
            {
                for (int j = 0; j < BlakWhiteImage.GetLength(2); j++)
                {
                    if (BlakWhiteImage[0, i, j] < 100)
                    {
                        ArrLine[i]++;
                        ArrColumn[j]++; 
                    }
                }
            }
            int TPoint = 0;
            int BPoint = 0;
            int HaightCount = 0;
            int Top = 0, Bottom = 0, Haight = 0;
            bool flag = false;
            for (int i = 0; i < ArrLine.Length; i++)
            {
                if ((ArrLine[i] > 5) && (!flag))
                {
                    Top = i;
                    flag = true;
                    continue;
                }
                if (((ArrLine[i] < 5) && (flag)) || ((i == ArrLine.Length - 1) && (flag)))
                {
                    Bottom = i;
                    Haight = Bottom - Top;
                    if (Haight > HaightCount)
                    {
                        HaightCount = Haight;
                        TPoint = Top;
                        BPoint = Bottom;                       
                    }
                    Haight = 0;
                    Top = 0;
                    Bottom = 0;
                    flag = false;
                    continue;
                } 
            }

            int LPoint = 0;
            int RPoint = 0;
            int WidhtCount = 0;
            int Left = 0, Right = 0, Widht = 0;
            flag = false;
            for (int i = 0; i < ArrColumn.Length; i++)
            {
                if ((ArrColumn[i] > 5) && (!flag))
                {
                    Left = i;
                    flag = true;
                    continue;
                }

                if (((ArrColumn[i] < 5) && (flag)) || ((i == ArrColumn.Length - 1) && (flag)))
                {
                    Right = i;
                    Widht = Right - Left;
                    if (Widht > WidhtCount)
                    {
                        WidhtCount = Widht;
                        LPoint = Left;
                        RPoint = Right;                       
                    }
                    Widht = 0;
                    Left = 0;
                    Right = 0;
                    flag = false;
                    continue;
                }
            }

            if (LPoint - 5 > 0)
            {
                LPoint = LPoint - 5;
            }
            else 
            {
                LPoint = 0;
            }

            if (TPoint - 5 > 0)
            {
                TPoint = TPoint - 5;
            }
            else 
            {
                TPoint = 0;
            }

            if (RPoint + 5 < ArrColumn.Length)
            {
                RPoint = RPoint + 5;
            }
            else
            {
                RPoint = ArrColumn.Length - 1;
            }

            if (BPoint + 5 < ArrLine.Length)
            {
                BPoint = BPoint + 5;
            }
            else
            {
                BPoint = ArrLine.Length - 1;
            }
            HaightCount = BPoint - TPoint;
            WidhtCount = RPoint - LPoint;



            for (int i = LPoint; i < RPoint; i++)
            {
                ColorImage[0, TPoint, i] = 255;
                ColorImage[0, BPoint, i] = 255;
                ColorImage[1, TPoint, i] = 0;
                ColorImage[1, BPoint, i] = 0;
                ColorImage[2, TPoint, i] = 255;
                ColorImage[2, BPoint, i] = 255;
               
            }
            for (int j = TPoint; j < BPoint; j++)
            {
                ColorImage[0, j, LPoint] = 255;
                ColorImage[0, j, RPoint] = 255;
                ColorImage[1, j, LPoint] = 0;
                ColorImage[1, j, RPoint] = 0;
                ColorImage[2, j, LPoint] = 255;
                ColorImage[2, j, RPoint] = 255;
            }

            Helper.ImageFromStartFormVideoPB = Colors.RgbToBitmap(ColorImage);
            byte[, ,] ScaledImage = new byte[3, HaightCount, WidhtCount];
            for (int i = 0; i < HaightCount; i++)
            {
                for (int j = 0; j < WidhtCount; j++)
                {
                    ScaledImage[0, i, j] = BlakWhiteImage[0, TPoint + i, LPoint + j];
                    ScaledImage[1, i, j] = BlakWhiteImage[1, TPoint + i, LPoint + j];
                    ScaledImage[2, i, j] = BlakWhiteImage[2, TPoint + i, LPoint + j]; 
                }
            }
            Helper.ImageFromStartFormScaledBunary = ScaleImage(Colors.RgbToBitmap(ScaledImage), 50, 50);

        }

        public static byte[, ,] RGBDetection(byte[, ,] srcImage)
        {
            byte[, ,] res = new byte[srcImage.GetLength(0), srcImage.GetLength(1), srcImage.GetLength(2)];
            for (int i = 0; i < res.GetLength(1); i++)
            {
                for (int j = 0; j < res.GetLength(2); j++)
                {
                    if ((srcImage[0, i, j] > Helper.ColorsSettFrRmin)
                        && (srcImage[0, i, j] < Helper.ColorsSettFrRmax) 
                        && (srcImage[1, i, j] > Helper.ColorsSettFrGmin)
                        && (srcImage[1, i, j] < Helper.ColorsSettFrGmax)
                        && (srcImage[2, i, j] > Helper.ColorsSettFrB)
                        && (srcImage[0, i, j] - srcImage[1, i, j] > Helper.ColorsSettFrRG) 
                        && (srcImage[0, i, j] > srcImage[2, i, j]))
                    {
                        res[0, i, j] = srcImage[0, i, j];
                        res[1, i, j] = srcImage[1, i, j];
                        res[2, i, j] = srcImage[2, i, j];
                    }
                    else
                    {
                        res[0, i, j] = 255;
                        res[1, i, j] = 255;
                        res[2, i, j] = 255;

                    }
                }
            }
            return res;
        }

        public static byte[, ,] HSVDetection(byte[, ,] srcImage)
        {
            byte[, ,] res = new byte[srcImage.GetLength(0), srcImage.GetLength(1), srcImage.GetLength(2)];
            for (int i = 0; i < res.GetLength(1); i++)
            {
                for (int j = 0; j < res.GetLength(2); j++)
                {
                    double H = 0, S = 0, V = 0, Cr = 0, Cg = 0, Cb = 0, Temp = 0;
                    double R, G, B;
                    R = (double)srcImage[0, i, j] / 255.0;
                    G = (double)srcImage[1, i, j] / 255.0;
                    B = (double)srcImage[2, i, j] / 255.0;

                    if ((R >= G) && (R >= B))
                    {
                        V = R;
                    }
                    else if ((G >= R) && (G >= B))
                    {
                        V = G;
                    }
                    else
                    {
                        V = B;
                    }

                    /*if (V == 0)
                    {
                        res[0, i, j] = 255;
                        res[1, i, j] = 255;
                        res[2, i, j] = 255;
                        break;
                    }*/

                    if ((R <= G) && (R <= B))
                    {
                        Temp = R;
                    }
                    else if ((G <= R) && (G <= B))
                    {
                        Temp = G;
                    }
                    else
                    {
                        Temp = B;
                    }

                    S = (V - Temp) / V;
                    Cr = (V - R) / (V - Temp);
                    Cg = (V - G) / (V - Temp);
                    Cb = (V - B) / (V - Temp);

                    if (R == V)
                    {
                        H = (Cb - Cg) * 60;
                    }
                    if (G == V)
                    {
                        H = (2 + Cr - Cb) * 60;
                    }
                    if (B == V)
                    {
                        H = (4 + Cg - Cr) * 60;
                    }

                    if (H < 0)
                    {
                        H = H + 360;
                    }                                       

                    if ((H < Helper.ColorsSettFrHmax) 
                        && (H > Helper.ColorsSettFrHmin)
                        && (V > Helper.ColorsSettFrVmin) 
                        && (V < Helper.ColorsSettFrVmax)
                        && (S < Helper.ColorsSettFrSmax)
                        && (S > Helper.ColorsSettFrSmin))
                    {
                        res[0, i, j] = srcImage[0, i, j];
                        res[1, i, j] = srcImage[1, i, j];
                        res[2, i, j] = srcImage[2, i, j];
                    }
                    else
                    {
                        res[0, i, j] = 255;
                        res[1, i, j] = 255;
                        res[2, i, j] = 255;
                    }

                }
            }
            return res;
        }

        public static byte[, ,] YCbCrDetection(byte[, ,] srcImage)
        {
            byte[, ,] res = new byte[srcImage.GetLength(0), srcImage.GetLength(1), srcImage.GetLength(2)];
            for (int i = 0; i < res.GetLength(1); i++)
            {
                for (int j = 0; j < res.GetLength(2); j++)
                {
                    double Y = 0, Cb = 0, Cr = 0;
                    double R, G, B;
                    R = (double)srcImage[0, i, j] / 255.0;
                    G = (double)srcImage[1, i, j] / 255.0;
                    B = (double)srcImage[2, i, j] / 255.0;

                    Y = 0.299 * R + 0.587 * G + 0.114 * B;
                    Cb = -0.168736 * R + -0.331264 * G + 0.5 * B;
                    Cr = 0.5 * R + -0.418688 * G + -0.081312 * B;

                    /*
                     * Доработать
                     */

                    if ((Y > Helper.ColorsSettFrYmin) 
                        && (Y < Helper.ColorsSettFrYmax) 
                        && (Cb > Helper.ColorsSettFrCbmin) 
                        && (Cb < Helper.ColorsSettFrCbmax) 
                        && (Cr > Helper.ColorsSettFrCrmin) 
                        && (Cr < Helper.ColorsSettFrCrmax))
                    {
                        res[0, i, j] = srcImage[0, i, j];
                        res[1, i, j] = srcImage[1, i, j];
                        res[2, i, j] = srcImage[2, i, j];
                    }
                    else 
                    {
                        res[0, i, j] = 255;
                        res[1, i, j] = 255;
                        res[2, i, j] = 255;
                    }
                    
                }
            }
            return res;
        }

        public static Image ScaleImage(Image source, int width, int height)
        {
            Image dest = new Bitmap(width, height);
            using (Graphics gr = Graphics.FromImage(dest))
            {
                gr.FillRectangle(Brushes.White, 0, 0, width, height);  // Очищаем экран
                gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;


                float srcwidth = source.Width;
                float srcheight = source.Height;
                float dstwidth = width;
                float dstheight = height;

                if (srcwidth <= dstwidth && srcheight <= dstheight)  // исходное изображение меньше целевого
                {
                    int left = (width - source.Width) / 2;
                    int top = (height - source.Height) / 2;
                    gr.DrawImage(source, left, top, source.Width, source.Height);
                }

                if (srcwidth >= dstwidth && srcheight >= dstheight)  // исходное изображение больше целевого
                {
                    int left = (width - source.Width) * 2;
                    int top = (height - source.Height) * 2;
                    gr.DrawImage(source, left, top, source.Width, source.Height);
                }


                gr.FillRectangle(Brushes.White, 0, 0, width, height);  // Очищаем экран

                if (srcwidth / srcheight > dstwidth / dstheight)  // Пропорции исходного изображения более широкие
                {
                    float cy = srcheight / srcwidth * dstwidth;
                    float top = ((float)dstheight - cy) / 2.0f;
                    if (top < 1.0f) top = 0;
                    gr.DrawImage(source, 0, top, dstwidth, cy);
                }
                else  // Пропорции исходного изображения более узкие
                {
                    float cx = srcwidth / srcheight * dstheight;
                    float left = ((float)dstwidth - cx) / 2.0f;
                    if (left < 1.0f) left = 0;
                    gr.DrawImage(source, left, 0, cx, dstheight);
                }

                return dest;
            }
        }

        public static double[] ByteRGBToBynaryArr(byte[, ,] srcImage)
        {
            double[] Result = new double[srcImage.GetLength(1)*srcImage.GetLength(2)];
            for (int i = 0; i < srcImage.GetLength(1); i++)
            {
                for (int j = 0; j < srcImage.GetLength(2); j++)
                {
                    if (srcImage[0, i, j] < 100)
                    {
                        Result[srcImage.GetLength(1) * i + j] = 1.0;
                    }
                    else
                    {
                        Result[srcImage.GetLength(1) * i + j] = 0.0;
                    }
                } 
            }
            return Result;
        }


    }
}
